/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.gac.ui;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import org.gac.stepmanager.StepTypeWrapper;
import org.gac.stepmanager.StepTypeWrapperDataFlavor;
import org.netbeans.api.visual.action.AcceptProvider;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.ConnectorState;
import org.netbeans.api.visual.border.BorderFactory;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;

/**
 *
 * @author Tomek
 */
public class BoxScene extends Scene
{

    private LayerWidget _connectionLayer;
    private LayerWidget _mainLayer;
    private LinkedList<DropAreaWidget> _dropAreaWidgets = new LinkedList<DropAreaWidget>();
    private StepWidgetBase _selectedStepWidget;

    public BoxScene()
    {

        _mainLayer = new LayerWidget(this);
        _mainLayer.setBorder(BorderFactory.createEmptyBorder(20));
        _connectionLayer = new LayerWidget(this);

        this.addChild(_mainLayer);

        this.addChild(_connectionLayer);

        addActions();
    }

//    public LayerWidget getDropAreaLayer()
//    {
//        return _dropAreaLayer;
//    }
    public void addDropAreaWidget(DropAreaWidget widget)
    {
        _dropAreaWidgets.add(widget);
    }

    @Override
    public JComponent createView()
    {
        JComponent result = super.createView();
        //Actionfa
        return result;
    }

//    public void setDropAreasVisible(boolean visible)
//    {
//        for (DropAreaWidget w : _dropAreaWidgets)
//        {
//            w.setDropAreaVisible(visible);
//        }
//
//
//    }

    public LayerWidget getConnectionLayer()
    {
        //return _mainLayer;
        return _connectionLayer;
    }

    public LayerWidget getMainLayer()
    {
        return _mainLayer;
    }

    public Iterable<DropAreaWidget> getDropAreas()
    {
        return Collections.unmodifiableCollection(_dropAreaWidgets);
    }

    public DropAreaWidget FindBestDropArea(Widget dragged, Point arg2)
    {
        //int maxDist = Integer.MAX_VALUE;
        DropAreaWidget bestDropArea = null;

        Point p;
        if (dragged != null)
        {
            p = dragged.convertLocalToScene(arg2);
        } else
        {
            p = arg2;
        }

        for (DropAreaWidget w : _dropAreaWidgets)
        {
            Rectangle r = w.convertLocalToScene(w.getBounds());
            r.grow(20, 20);
            if (r.contains(p))
            {
                bestDropArea = w;
            }
        }

        turnHighlightOff();
        if (bestDropArea != null)
        {
            bestDropArea.setHighlight(true);
        }
        return bestDropArea;
    }

    void removeDropAreaWidget(DropAreaWidget dropArea)
    {
        _dropAreaWidgets.remove(dropArea);
    }

    void stepWidgetSelected( StepWidgetBase swb )
    {
        if( _selectedStepWidget != null )
            _selectedStepWidget.setSelection(false);
        _selectedStepWidget = swb;

        if( _selectedStepWidget != null )
            _selectedStepWidget.setSelection(true);

        System.out.println("selected: " + swb._modelStep.getName());
        if( _selectionListener != null )
            _selectionListener.selectionChanged(swb);
    }

    private void addActions()
    {
        this.getActions().addAction(ActionFactory.createZoomAction());
        this.getActions().addAction(ActionFactory.createPanAction());
        this.getActions().addAction(ActionFactory.createAcceptAction(new AcceptProvider()
        {

            public ConnectorState isAcceptable(Widget widget, Point point,
                    Transferable transferable)
            {
                StepTypeWrapper stw = getStepTypeWrapperFromTransferable(
                        transferable);

                if (stw == null)
                {
                    return ConnectorState.REJECT_AND_STOP;
                }

                DropAreaWidget daw =
                        FindBestDropArea(null, point);
                if (daw != null)
                {
                    return ConnectorState.ACCEPT;
                } else
                {
                    return ConnectorState.REJECT;
                }
            }

            public void accept(Widget widget, Point point,
                    Transferable transferable)
            {
                DropAreaWidget daw =
                        FindBestDropArea(null, point);
                if (daw != null)
                {
                    StepTypeWrapper stw = getStepTypeWrapperFromTransferable(
                            transferable);
                    if (stw == null)
                    {
                        return;
                    }
                    String stepName = JOptionPane.showInputDialog(
                            "Enter step name", stw.getName());
                    daw.Drop(stw.createStepInstance(stepName));
                }
            }

            private StepTypeWrapper getStepTypeWrapperFromTransferable(
                    Transferable transferable)
            {
                try
                {
                    return (StepTypeWrapper) transferable.getTransferData(
                            StepTypeWrapperDataFlavor.Instance);
                } catch (UnsupportedFlavorException ex)
                {
                    return null;
                } catch (IOException ex)
                {
                    return null;
                }
            }
        }));
    }

    public void turnHighlightOff()
    {
        for (DropAreaWidget w : _dropAreaWidgets)
        {
            w.setHighlight(false);
        }
    }

    public void clear()
    {
        _mainLayer.removeChildren();
        _connectionLayer.removeChildren();
        _dropAreaWidgets.clear();
    }

    private SelectionListener _selectionListener;
    public void setSelectionListener( SelectionListener listener )
    {
        _selectionListener = listener;
    }

    public interface SelectionListener
    {
        void selectionChanged( StepWidgetBase newSelection );
    }
}
